/* Copyright [2023] <gyl> */
#include <memory>

#include "sql/operator/logical_operator.h"
#include "sql/operator/predicate_logical_operator.h"
#include "sql/operator/aggr_logical_operator.h"
#include "sql/operator/table_get_logical_operator.h"
#include "sql/operator/join_logical_operator.h"
#include "sql/optimizer/physical_plan_generator.h"
#include "sql/optimizer/logical_plan_generator.h"
#include "sql/stmt/utils.h"
#include "common/global_context.h"
#include "storage/db/db.h"

#include "sql/stmt/stmt.h"
#include "sql/stmt/select_stmt.h"
#include "sql/stmt/filter_stmt.h"

using std::unique_ptr;

RC Utils::close(unique_ptr<PhysicalOperator> &operator_) {
  if (nullptr == operator_) {
    return RC::INVALID_ARGUMENT;
  }
  RC rc = operator_->close();
  if (rc != RC::SUCCESS) {
    LOG_WARN("failed to close operator. rc=%s", strrc(rc));
  }
  operator_.reset();
  return rc;
}

RC Utils::open(unique_ptr<PhysicalOperator> &operator_, Db *db_) {
  if (nullptr == operator_) {
    return RC::INVALID_ARGUMENT;
  }
  Trx *trx = GCTX.trx_kit_->create_trx(db_->clog_manager());
  trx->start_if_need();
  return operator_->open(trx);
}

RC Utils::next_tuple(unique_ptr<PhysicalOperator> &operator_, Tuple *&tuple) {
  RC rc = operator_->next();
  if (rc != RC::SUCCESS) {
    return rc;
  }
  tuple = operator_->current_tuple();
  return rc;
}

RC Utils::get_value(Stmt *select_stmt, std::vector<Value> &values, Db *db_,
                    bool &flag) {
  unique_ptr<LogicalOperator> logical_operator;
  LogicalPlanGenerator logical_generator_;
  RC rc = RC::SUCCESS;
  rc = logical_generator_.create(select_stmt, logical_operator);
  if (rc != RC::SUCCESS) {
    return rc;
  }
  unique_ptr<PhysicalOperator> physical_operator;
  PhysicalPlanGenerator physical_generator_;
  rc = physical_generator_.create(*logical_operator, physical_operator);
  if (rc != RC::SUCCESS) {
    return rc;
  }
  rc = open(physical_operator, db_);
  Tuple *tuple = nullptr;
  while (RC::SUCCESS == (next_tuple(physical_operator, tuple))) {
    assert(tuple != nullptr);
    int cell_num = tuple->cell_num();
    // 要求筛选出的列只能为1列
    if (cell_num > 1) {
      flag = true;  // 标记子查询返回了多列，只有在CompOp为EXISTS、NOT
                    // EXISTS时才合法
    }
    for (int i = 0; i < cell_num; i++) {
      Value value;
      RC rc = tuple->cell_at(i, value);
      if (rc != RC::SUCCESS) {
        return rc;
      }
      values.emplace_back(value);
    }
  }
  rc = close(physical_operator);
  return rc;
}
